package com.wps.wdztv6.common;

import com.alibaba.fastjson.JSON;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.http.HttpEntity;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.AuthSchemes;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.BasicHttpEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Map;

@Log4j2
public class HttpPostUtil {
    /**
     * 下载请求
     *
     * @param url
     * @param headers
     * @return
     * @throws IOException
     */
    public static void sendGetDownloadRequest(String url, Map<String, String> headers,String savePath) throws IOException {
        // 设置请求头
        HttpGet request = new HttpGet(url);
        if (null != headers) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                request.addHeader(entry.getKey(), entry.getValue());
            }
        }

        // 发送http请求
        try (CloseableHttpClient httpClient = HttpClients.createDefault();
             CloseableHttpResponse response = httpClient.execute(request)) {
            HttpEntity entity = response.getEntity();
            if (null != entity) {
                InputStream in = entity.getContent();
                File file = new File(savePath);//这里为存储路径/xx/xx..
                FileOutputStream fout = new FileOutputStream(file);
                int a = -1;
                byte[] tmp = new byte[1024];
                while ((a = in.read(tmp)) != -1) {
                    fout.write(tmp, 0, a);
                }
                fout.flush();
                fout.close();
                in.close();
                httpClient.close();
                return;
            }
            throw new IOException("No response");
        } catch (IOException e) {
            log.error(e);
            throw e;
        }
    }
    /**
     * 发送Get请求(如果https请求需要忽略证书检测，需自己实现)
     *
     * @param url
     * @param headers
     * @return
     * @throws IOException
     */
    public static <T> T sendGetRequest(String url, Map<String, String> headers,Class<T> classes) throws IOException {
        // 设置请求头
        HttpGet request = new HttpGet(url);
        if (null != headers) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                request.addHeader(entry.getKey(), entry.getValue());
            }
        }
        // 发送http请求
        try (CloseableHttpClient httpClient = HttpClients.createDefault();
             CloseableHttpResponse response = httpClient.execute(request)) {
            HttpEntity entity = response.getEntity();
            if (null != entity) {
                String content = EntityUtils.toString(entity, StandardCharsets.UTF_8);
                System.out.println(content);
                EntityUtils.consume(entity); // 关闭content stream
                return JSON.parseObject(content,classes);
            }
            throw new IOException("No response");
        } catch (IOException e) {
            log.error(e);
            throw e;
        }
    }

    /**
     * 发送Get请求(如果https请求需要忽略证书检测，需自己实现)
     */
    public static  <T> T  sendPostRequest(String url, String body, Map<String, String> headers,Class<T> classes) throws IOException {
        log.info("发送请求:{}", url);
        // 设置请求头
        HttpPost request = new HttpPost(url);
        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                request.addHeader(entry.getKey(), entry.getValue());
            }
        }
        // 设置请求body
        if (body != null) {
            request.setEntity(new StringEntity(body, StandardCharsets.UTF_8));
        }
        try {
            // 发送http请求
            CloseableHttpClient httpClient = HttpClients.createDefault();
            CloseableHttpResponse response = httpClient.execute(request);
            HttpEntity entity = response.getEntity();
            if (null != entity) {
                String content = EntityUtils.toString(entity);
                log.info("相应数据:{}",content);
                httpClient.close();
                response.close();
                return JSON.parseObject(content,classes);
            }
            return null;
        } catch (IOException e) {
            throw e;
        }
    }

    /**
     * 发送Put请求(如果https请求需要忽略证书检测，需自己实现)
     *
     * @param url
     * @param headers
     * @return
     * @throws IOException
     */
    public static CloseableHttpResponse sendPutRequest(String url, InputStream body, Map<String, String> headers) throws IOException {
        // 设置请求头
        HttpPut request = new HttpPut(url);
        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                request.addHeader(entry.getKey(), entry.getValue());
            }
        }
        // 设置请求body
        if (body != null) {
            InputStreamEntity entity = new InputStreamEntity(body);
            entity.setContentType(ContentType.APPLICATION_OCTET_STREAM.toString());
            request.setEntity(entity);
        }

        // 发送http请求
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            return httpClient.execute(request);
        } catch (ClientProtocolException e) {
            throw e;
        } catch (IOException e) {
            throw e;
        }
    }

    public static CloseableHttpResponse doPutUpload(String url, File file, Map<String, String> headers) {
        FileInputStream fileInputStream = null;
        CloseableHttpResponse response = null;
        try {
            // file
            fileInputStream = new FileInputStream(file);

            HttpPut httpput = new HttpPut(url);
            addHeader(httpput, headers);

            BasicHttpEntity basicHttpEntity = new BasicHttpEntity();
            basicHttpEntity.setChunked(false);
            basicHttpEntity.setContent(fileInputStream);
            basicHttpEntity.setContentLength(file.length());

            httpput.setEntity(basicHttpEntity);
            response = executeRequest(url, httpput);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                }catch (Exception e1){
                    e1.printStackTrace();
                }
            }
        }
        return response;
    }
    private static void addHeader(HttpRequestBase httpRequestBase, Map<String, String> header) {
        if (header != null && !header.isEmpty()) {
            for (Map.Entry<String, String> entry : header.entrySet()) {
                httpRequestBase.addHeader(entry.getKey(), entry.getValue());
            }
        }
    }

    private static CloseableHttpResponse executeRequest(String url, HttpUriRequest request) throws Exception {
        return getInstance(url).execute(request);
    }

    private static CloseableHttpClient getInstance(String url) {
        if (!StringUtils.isEmpty(url) && url.startsWith("https")) {
            return sslClient();
        } else {
            return HttpClients.createDefault();
        }
    }

    private static CloseableHttpClient sslClient() {
        try {
            // 在调用SSL之前需要重写验证方法，取消检测SSL
            X509TrustManager trustManager = new X509TrustManager() {
                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }

                @Override
                public void checkClientTrusted(X509Certificate[] xcs, String str) {
                }

                @Override
                public void checkServerTrusted(X509Certificate[] xcs, String str) {
                }
            };
            SSLContext ctx = SSLContext.getInstance(SSLConnectionSocketFactory.TLS);
            ctx.init(null, new TrustManager[]{trustManager}, null);
            SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(ctx, NoopHostnameVerifier.INSTANCE);
            // 创建Registry
            RequestConfig requestConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD_STRICT)
                    .setExpectContinueEnabled(Boolean.TRUE).setTargetPreferredAuthSchemes(Arrays.asList(AuthSchemes.NTLM, AuthSchemes.DIGEST))
                    .setProxyPreferredAuthSchemes(Arrays.asList(AuthSchemes.BASIC)).build();
            Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                    .register("http", PlainConnectionSocketFactory.INSTANCE)
                    .register("https", socketFactory).build();
            // 创建ConnectionManager，添加Connection配置信息
            PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
            CloseableHttpClient closeableHttpClient = HttpClients.custom().setConnectionManager(connectionManager)
                    .setDefaultRequestConfig(requestConfig).build();
            return closeableHttpClient;
        } catch (KeyManagementException ex) {
            throw new RuntimeException(ex);
        } catch (NoSuchAlgorithmException ex) {
            throw new RuntimeException(ex);
        }
    }

    /**
     * 发送Post请求(如果https请求需要忽略证书检测，需自己实现)
     *
     * @param url
     * @param headers
     * @return
     * @throws IOException
     */
    public static Pair<StatusLine, String> sendPostRequest3(String url, String body, Map<String, String> headers) throws IOException {
        // 设置请求头
        HttpPost request = new HttpPost(url);
        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                request.addHeader(entry.getKey(), entry.getValue());
            }
        }
        // 设置请求body
        if (body != null) {
            request.setEntity(new StringEntity(body, StandardCharsets.UTF_8));
        }

        // 发送http请求
        try (CloseableHttpClient httpClient = HttpClients.createDefault();
             CloseableHttpResponse response = httpClient.execute(request)) {
            HttpEntity entity = response.getEntity();
            if (null != entity) {
                String content = EntityUtils.toString(entity, StandardCharsets.UTF_8);
                EntityUtils.consume(entity); // 关闭content stream
                return Pair.of(response.getStatusLine(), content);
            }
            throw new IOException("No response");
        } catch (ClientProtocolException e) {
            throw e;
        } catch (IOException e) {
            throw e;
        }
    }

}
